using System;
using System.Collections.Generic;
using System.Text;

namespace Zsa.Emulation.Input
{
    /// <summary>
    /// Encapsulates input register and exposes it to the 
    /// controller render classes.
    /// </summary>
    public class InputRegister
    {
        #region Fields
        /// <summary>
        /// The register read count.
        /// </summary>
        private byte _RegisterReadCount;

        /// <summary>
        /// The value of the register.
        /// </summary>
        private byte _Signature = 0;

        /// <summary>
        /// Register one values.
        /// </summary>
        internal byte _RegisterOne = 0;

        /// <summary>
        /// Register two values.
        /// </summary>
        internal byte _RegisterTwo = 0;

        /// <summary>
        /// The input device type.
        /// </summary>
        private NesInputDeviceType _DeviceType;

        private bool _InStrobe;
        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:InputRegister"/> class.
        /// </summary>
        internal InputRegister(NesInputDeviceType deviceType)
        {
            _DeviceType = deviceType;
            SetSignature(deviceType);
        }
        #endregion Constructor

        #region Methods
        /// <summary>
        /// Reads this instance.
        /// </summary>
        /// <returns></returns>
        internal byte Read()
        {
             byte _Value = 0;
            if (_RegisterReadCount < 8)
            {
                _Value =(byte)
                    ((_RegisterOne >> _RegisterReadCount)&1);
            }
            else if (_RegisterReadCount < 16)
            {
                _Value = (byte)
                    ((_RegisterTwo >> _RegisterReadCount-8)&1);
            }
            else if (_RegisterReadCount < 20)
            {
                _Value = (byte)
                    ((_Signature >> _RegisterReadCount - 16) & 1);
            }
            if (_RegisterReadCount == 23)
            {
                _RegisterReadCount = 0xFF;
            }
            _RegisterReadCount++;
            return (byte)(_Value);
        }
        internal byte ReadCount
        {
            get
            {
                return _RegisterReadCount;
            }
            set
            {
                _RegisterReadCount = value;
            }
        }
        /// <summary>
        /// Writes the specified data.
        /// </summary>
        /// <param name="data">The data.</param>
        internal void Write(byte data)
        {
            if (_InStrobe && data == 0)
            {
                ReadCount = 0;
            }
            else if (data == 1)//&& !_InStrobe)
            {
                _InStrobe = true;
            }
            else
            {
                _InStrobe = false;
            }
        }

        /// <summary>
        /// Sets the signature.
        /// </summary>
        /// <param name="inputDeviceType">Type of the input device.</param>
        internal void SetSignature(NesInputDeviceType inputDeviceType)
        {
            // Check if port one.
            bool _Port1 = (inputDeviceType & NesInputDeviceType.PortTwo) == NesInputDeviceType.PortTwo;
            // Remove the flag.
            if (_Port1)
            {
                inputDeviceType ^= NesInputDeviceType.PortTwo;
            }
            switch (inputDeviceType)
            {
                //case NesInputDeviceType.StandardController:
                //    if (_Port1)
                //    {
                //        _Signature = 32;
                //    }
                //    else 
                //    {
                //        _Signature = 16;
                //    }
                //    break;
                default:
                    _Signature = 0;
                    break;
            }
        }
        #endregion Methods

        #region Properties





        /// <summary>
        /// Gets or sets the type of the register.
        /// </summary>
        /// <value>The type of the register.</value>
        internal NesInputDeviceType RegisterType
        {
            get
            {
                return _DeviceType;
            }
            set
            {
                _DeviceType = value;
                SetSignature(_DeviceType);
            }
        
        }
        #endregion Properties
    }
}
